package cn.ztuo.bitrade.controller;


import cn.ztuo.bitrade.constant.SysConstant;
import cn.ztuo.bitrade.entity.*;
import cn.ztuo.bitrade.processor.CoinProcessor;
import cn.ztuo.bitrade.processor.CoinProcessorFactory;
import cn.ztuo.bitrade.service.*;
import cn.ztuo.bitrade.util.*;
import cn.ztuo.bitrade.waiting.WaitingOrder;
import cn.ztuo.bitrade.waiting.WaitingOrderFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

@Slf4j
@RestController
public class MarketController extends BaseController {
    @Autowired
    private MarketService marketService;
    @Autowired
    private ContractCoinService coinService;
    @Autowired
    private CoinProcessorFactory coinProcessorFactory;
    @Autowired
    private ContractTradeService ContractTradeService;
    @Autowired
    private ContractOrderService orderService;
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private WaitingOrderFactory factory;

    @Autowired
    private RedisUtil redisUtil;


    /**
     * 查询默认交易对儿
     *
     * @return
     */
    @RequestMapping(value = "default/symbol")
    public MessageResult findDefaultSymbol() {
        Object redisResult = redisUtil.get(SysConstant.DEFAULT_SYMBOL);
        JSONObject jsonObject = new JSONObject();
        if (redisResult == null) {
            ContractCoin ContractCoin = coinService.getBaseSymbol().get(0);
            if (ContractCoin != null) {
                String result = ContractCoin.getCoinSymbol() + "_" + ContractCoin.getBaseSymbol();
                //toUpperCase()转换大写
                jsonObject.put("app", ContractCoin.getSymbol().toUpperCase());
                jsonObject.put("web", result.toUpperCase());
                redisUtil.set(SysConstant.DEFAULT_SYMBOL, jsonObject);
                return success(jsonObject);
            } else {
                jsonObject.put("app", "BTC/USDT");
                jsonObject.put("web", "BTC_USDT");
                return success(jsonObject);
            }
        } else {
            return success(redisResult);
        }
    }


    /**
     * 查询待触发队列中信息
     *
     * @param symbol
     * @param orderId
     * @param direction
     * @return
     */
    @RequestMapping("find/waiting")
    public ContractOrder findWaitingOrder(String symbol, String orderId, ContractOrderDirection direction) {
        WaitingOrder waitingOrder = factory.getWaitingOrder(symbol);
        ContractOrder order = orderService.findOne(orderId);
        order = waitingOrder.findWaitingOrder(order, direction);
        return order;
    }

    /**
     * 获取支持的交易币种
     *
     * @return
     */
    @RequestMapping("symbol")
    public List<ContractCoin> findAllSymbol() {
        List<ContractCoin> coins = coinService.findAllEnabled();
        return coins;
    }

    @RequestMapping("overview")
    public Map<String, List<CoinThumb>> overview() throws IOException {
        log.info("/market/overview");
        Calendar calendar = Calendar.getInstance();
        //将秒、微秒字段置为0
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        long nowTime = calendar.getTimeInMillis();
        calendar.add(Calendar.HOUR_OF_DAY, -24);
        long firstTimeOfToday = calendar.getTimeInMillis();
        Map<String, List<CoinThumb>> result = new HashMap<>();
        List<ContractCoin> recommendCoin = ContractUtils.findBaseSymbols();
        List<CoinThumb> recommendThumbs = new ArrayList<>();
        for (ContractCoin coin : recommendCoin) {
            CoinProcessor processor = coinProcessorFactory.getProcessor(coin.getSymbol());
            if (processor != null) {
                CoinThumb thumb = processor.getThumb();
                List<KLine> lines = marketService.findAllKLine(thumb.getSymbol(), firstTimeOfToday, nowTime, "1hour");
                List<BigDecimal> trend = new ArrayList();
                for (KLine line : lines) {
                    trend.add(line.getClosePrice());
                }
                thumb.setTrend(trend);
                recommendThumbs.add(thumb);
            }
        }
        result.put("recommend", recommendThumbs);
        List<CoinThumb> allThumbs = findSymbolThumb(false);
        Collections.sort(allThumbs, (o1, o2) -> o2.getChg().compareTo(o1.getChg()));
        int limit = allThumbs.size() > 5 ? 5 : allThumbs.size();
        result.put("changeRank", allThumbs.subList(0, limit));
        return result;
    }


    /**
     * 获取某交易对详情
     *
     * @param symbol
     * @return
     */
    @RequestMapping("symbol-info")
    public ContractCoin findSymbol(String symbol) {
        ContractCoin coin = ContractUtils.getBaseSymbol(symbol);
        return coin;
    }

    /**
     * 获取币种缩略行情
     *
     * @return
     */
    @RequestMapping("symbol-thumb")
    public List<CoinThumb> findSymbolThumb(Boolean isLever) {
        List<CoinThumb> thumbs = new ArrayList<>();
        long a = System.currentTimeMillis();
        Map<String, BigDecimal> indexPriceMap = ContractUtils.getIndexprice();
        Map<String, BigDecimal> marketPriceMap = ContractUtils.getMarketprice();

        List<ContractCoin> coins = coinService.findAllEnabled();
        for (ContractCoin coin : coins) {
            CoinProcessor processor = coinProcessorFactory.getProcessor(coin.getSymbol());
            if (processor != null) {
                CoinThumb thumb = processor.getThumb();
                JSONObject json = JSON.parseObject(JSON.toJSONString(coin));
                json.put("indexPrice", indexPriceMap.get(thumb.getSymbol()));
                json.put("marketPrice", marketPriceMap.get(thumb.getSymbol()));
                thumb.setContractCoin(json);
                thumbs.add(thumb);
            }
        }
        return thumbs;
    }


//    /**
//     * 获取币种缩略行情
//     *
//     * @return
//     */
//    @RequestMapping("symbol-thumb")
//    public List<CoinThumb> findSymbolThumb(Boolean isLever) throws IOException {
//        List<CoinThumb> thumbs = new ArrayList<>();
//        long a = System.currentTimeMillis();
//        log.info("start symbol-thumb : " + System.currentTimeMillis());
//        Map<String, BigDecimal> indexPriceMap = ContractUtils.getIndexprice();
//        Map<String, BigDecimal> marketPriceMap = ContractUtils.getMarketprice();
//        log.info("end symbol-thumb : " + System.currentTimeMillis());
//        log.info("耗时 : " + (System.currentTimeMillis() - a) / 1000);
//
//        log.info("indexPriceMap : " + JSON.toJSONString(indexPriceMap));
//        log.info("marketPriceMap : " + JSON.toJSONString(marketPriceMap));
//
//        List<ContractCoin> coins = coinService.findAllEnabled();
//        for (ContractCoin coin : coins) {
//            CoinProcessor processor = coinProcessorFactory.getProcessor(coin.getSymbol());
//            if (processor != null) {
//                String url = "https://api.btcgateway.pro/swap-ex/market/detail/merged?contract_code="+coin.getCoinSymbol()+"-USD";
//                String result = HttpsUtil.doGet(url);
//                JSONObject obj = JSON.parseObject(result);
//                if (obj.containsKey("status") && "ok".equals(obj.get("status"))) {
//                    JSONObject json = obj.getJSONObject("tick");
//                    CoinThumb thumb = processor.getThumb();
//                    thumb.setChange(json.getBigDecimal("close").subtract(json.getBigDecimal("open")));
//                    thumb.setClose(json.getBigDecimal("close"));
//                    thumb.setHigh(json.getBigDecimal("high"));
//                    thumb.setLow(json.getBigDecimal("low"));
//                    thumb.setOpen(json.getBigDecimal("open"));
//                    thumb.setVolume(json.getBigDecimal("vol"));
//                }
//                CoinThumb thumb = processor.getThumb();
//                JSONObject json = JSON.parseObject(JSON.toJSONString(coin));
//                json.put("indexPrice", indexPriceMap.get(thumb.getSymbol()));
//                json.put("marketPrice", marketPriceMap.get(thumb.getSymbol()));
//                thumb.setContractCoin(json);
//                thumbs.add(thumb);
//            }
//        }
//        return thumbs;
//    }

    @RequestMapping("symbol-thumb-trend")
    public JSONArray findSymbolThumbWithTrend() {
        List<ContractCoin> coins = coinService.findAllEnabled();
        //List<CoinThumb> thumbs = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        //将秒、微秒字段置为0
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        long nowTime = calendar.getTimeInMillis();
        calendar.add(Calendar.HOUR_OF_DAY, -24);
        JSONArray array = new JSONArray();
        long firstTimeOfToday = calendar.getTimeInMillis();
        for (ContractCoin coin : coins) {
            CoinProcessor processor = coinProcessorFactory.getProcessor(coin.getSymbol());
            CoinThumb thumb = processor.getThumb();
            JSONObject json = (JSONObject) JSON.toJSON(thumb);
            json.put("zone", 0);
            List<KLine> lines = marketService.findAllKLine(thumb.getSymbol(), firstTimeOfToday, nowTime, "1hour");
            JSONArray trend = new JSONArray();
            for (KLine line : lines) {
                trend.add(line.getClosePrice());
            }
            json.put("trend", trend);
            array.add(json);
        }
        return array;
    }

    /**
     * 获取币种历史K线
     *
     * @param symbol
     * @param from
     * @param to
     * @param resolution
     * @return
     */
    @RequestMapping("history")
    public JSONArray findKHistory(String symbol,long from,long to,String resolution){
        String period = "";
        //.endsWith()查询字符串是以指定字符串结尾
        if(resolution.endsWith("H") || resolution.endsWith("h")){
            //.substring()截取字符串 拼接
            period = resolution.substring(0,resolution.length()-1) + "hour";
        }
        else if(resolution.endsWith("D") || resolution.endsWith("d")){
            period = resolution.substring(0,resolution.length()-1) + "day";
        }
        else if(resolution.endsWith("W") || resolution.endsWith("w")){
            period = resolution.substring(0,resolution.length()-1) + "week";
        }
        else if(resolution.endsWith("M") || resolution.endsWith("m")){
            period = resolution.substring(0,resolution.length()-1) + "month";
        }
        else{
            Integer val = Integer.parseInt(resolution);
            if(val < 60) {
                period = resolution + "min";
            }
            else {
                period = (val/60) + "hour";
            }
        }
        List<KLine> list = marketService.findAllKLine(symbol,from,to,period);

        JSONArray array = new JSONArray();
        for(KLine item:list){
            JSONArray group = new JSONArray();
            group.add(0,item.getTime());
            group.add(1,item.getOpenPrice());
            group.add(2,item.getHighestPrice());
            group.add(3,item.getLowestPrice());
            group.add(4,item.getClosePrice());
            group.add(5,item.getVolume());
            array.add(group);
        }
        return array;
    }

    /**
     * 查询最近成交记录
     *
     * @param symbol 交易对符号
     * @param size   返回记录最大数量
     * @return
     */
    @RequestMapping("latest-trade")
    public List<ContractTrade> latestTrade(String symbol, int size) {
        ContractCoin ContractCoin = coinService.findBySymbol(symbol);
        List<ContractTrade> ContractTrades = ContractTradeService.findLatest(symbol, size);
        return ContractTrades;
    }

    @RequestMapping("contract-plate")
    public Map<String, List<TradePlateItem>> findTradePlate(String symbol) {
        //远程RPC服务URL,后缀为币种单位
        String serviceName = "SERVICE-Contract-TRADE";
        String url = "http://" + serviceName + "/monitor/plate?symbol=" + symbol;
        ResponseEntity<HashMap> result = restTemplate.getForEntity(url, HashMap.class);
        return (Map<String, List<TradePlateItem>>) result.getBody();
    }


    @RequestMapping("contract-plate-mini")
    public Map<String, JSONObject> findTradePlateMini(String symbol) {
        //远程RPC服务URL,后缀为币种单位
        String serviceName = "service-contract-trade";
        String url = "http://" + serviceName + "/monitor/plate-mini?symbol=" + symbol;
        ResponseEntity<HashMap> result = restTemplate.getForEntity(url, HashMap.class);
        return (Map<String, JSONObject>) result.getBody();
    }


    @RequestMapping("contract-plate-full")
    public Map<String, JSONObject> findTradePlateFull(String symbol) {
        //远程RPC服务URL,后缀为币种单位
        String serviceName = "SERVICE-Contract-TRADE";
        String url = "http://" + serviceName + "/monitor/plate-full?symbol=" + symbol;
        ResponseEntity<HashMap> result = restTemplate.getForEntity(url, HashMap.class);
        return (Map<String, JSONObject>) result.getBody();
    }


    @RequestMapping("cancelWaitingOrder")
    public MessageResult cancelWaitingOrder(@RequestBody JSONObject map) {
        String symbol = map.getString("symbol");
        String jsonStr = JSONArray.toJSONString(map.get("orders"));
        List<ContractOrder> orders = JSON.parseArray(jsonStr, ContractOrder.class);
        WaitingOrder waitingOrder = factory.getWaitingOrder(symbol);
        for (ContractOrder order : orders) {
            waitingOrder.cancel(order);
        }
        return MessageResult.success();
    }
}
